package com.sec.android.app.myfiles.feature.vi;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.FragmentTransaction;
import android.content.Context;
import android.graphics.Paint;
import android.support.v4.view.animation.PathInterpolatorCompat;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import android.view.animation.TranslateAnimation;
import android.widget.AbsListView;
import android.widget.GridView;

import com.airbnb.lottie.LottieAnimationView;
import com.altamirasoft.path_animation.PathLineAnimationView;
import com.altamirasoft.path_animation.PathListener;
import com.sec.android.app.myfiles.R;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.util.DPUtils;
import com.sec.android.app.myfiles.util.UiUtils;
import com.sec.android.app.myfiles.util.animation.AddDeleteGridAnimator;
import com.sec.android.app.myfiles.util.animation.AddDeleteListAnimator;
import com.sec.android.app.myfiles.util.animation.EmptyIconPathAnimatorListener;
import com.sec.android.app.myfiles.util.animation.interpolator.SineInOut33;
import com.sec.android.app.myfiles.util.animation.interpolator.SineInOut70;
import com.sec.android.app.myfiles.util.animation.interpolator.SineInOut90;

import java.util.ArrayList;

/**
 * VI effect Implement class.
 *
 * @author jae.bae
 */
public class ViEffectImp {
    private boolean mIsOnProgressDeleteVI = false;

    public ViEffectImp() {
        mAddDeleteGridAnimators = new SparseArray<>();
        mAddDeleteListAnimators = new SparseArray<>();
    }

    /**
     * VI effect for entering folder
     *
     * @param ft FragmentTransaction
     */
    public void enterFolder(FragmentTransaction ft) {
        ft.setCustomAnimations(R.animator.depth_in_current_view, R.animator.depth_in_previous_view);
    }

    /**
     * VI effect for leaving folder
     *
     * @param ft FragmentTransaction
     */
    public void leaveFolder(FragmentTransaction ft) {
        ft.setCustomAnimations(R.animator.depth_out_current_view, R.animator.depth_out_previous_view);
    }

    /**
     * VI effect for show folder
     *
     * @param ft FragmentTransaction
     */
    public void showFolder(FragmentTransaction ft) {
        ft.setCustomAnimations(R.animator.home_to_list_fade_in_current, R.animator.home_to_list_fade_in_previous);
    }

    public void fileSelectedBoxEffect(View mFileSelectedLayout, boolean bShow) {
        boolean bCurShow = false;
        if (mFileSelectedLayout.getVisibility() == View.VISIBLE) {
            bCurShow = true;
        }
        int duration = 333;
        if (bShow != bCurShow) {
            int height = (int) mFileSelectedLayout.getContext().getResources().getDimension(R.dimen.file_operation_view_height);
            if (bShow) {
                showFileSelectedBox(mFileSelectedLayout, height, duration);
            } else {
                hideFileSelectedBox(mFileSelectedLayout, height, duration);
            }
        }
    }

    private void showFileSelectedBox(final View view, int height, int duration) {
        int nFrom = height * 1;
        int nTo = 0;

        final Animation animation = new TranslateAnimation(0, 0, nFrom, nTo);
        animation.setInterpolator(PathInterpolatorCompat.create(0.33f, 0f, 0.2f, 1f));
        animation.setDuration(duration);
        animation.setFillAfter(true);

        view.postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setVisibility(View.VISIBLE);
                view.startAnimation(animation);
            }
        }, 300);
    }

    private void hideFileSelectedBox(final View view, int height, int duration) {
        int nFrom = 0;
        int nTo = height * 1;

        final Animation animation = new TranslateAnimation(0, 0, nFrom, nTo);
        animation.setInterpolator(PathInterpolatorCompat.create(0.33f, 0f, 0.2f, 1f));
        animation.setDuration(duration);
        animation.setFillAfter(false);
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                view.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });

        view.postDelayed(new Runnable() {
            @Override
            public void run() {
                view.startAnimation(animation);
            }
        }, 100);
    }

    /**
     * VI effect for show/Hide check box
     *
     * @param context
     * @param listView
     * @param bShow
     */
    public void showCheckBox(Context context, View listView, View actionbar, boolean bShow) {
        if (!(listView instanceof GridView)) { // Grid view is not supported

            // ToDo please find better way of get width
            int checkBoxWidth = (int) context.getResources().getDimension(R.dimen.list_item_checkbox_width);
            checkBoxWidth += (int) context.getResources().getDimension(R.dimen.list_item_checkbox_margin_left);

            if (!UiUtils.isInRTLMode(context)) {
                checkBoxWidth *= -1;
            }

            int nFrom = 0;
            int nTo = checkBoxWidth;

            if (!bShow) {
                nTo *= -1;
            }

            listView.setTranslationX(nTo);
            listView.animate().translationX(nFrom).setInterpolator(PathInterpolatorCompat.create(0.33f, 0f, 0.3f, 1f)).setDuration(500);

            if (bShow && actionbar != null) {
                actionbar.setTranslationX(nTo);
                actionbar.animate().translationX(nFrom).setInterpolator(PathInterpolatorCompat.create(0.33f, 0f, 0.3f, 1f)).setDuration(500);
            }
        }
    }


    private SparseArray<AddDeleteListAnimator> mAddDeleteListAnimators;
    private SparseArray<AddDeleteGridAnimator> mAddDeleteGridAnimators;
    private AbsMyFilesFragment mFragment;

    public void setDeleteListItem(int processId, Context context, AbsListView twListView, ArrayList<Integer> itemList) {
        if (!itemList.isEmpty()) {
            if (twListView instanceof GridView) {
                _setDeleteGridItem(processId, context, twListView, itemList);
                mIsOnProgressDeleteVI = true;
            } else {
                _setDeleteListItem(processId, context, twListView, itemList);
                mIsOnProgressDeleteVI = true;
            }
        }
    }

    public boolean doDeleteListItem(AbsMyFilesFragment fragment) {
        //TODO HYL 动画效果
        return false;

        /*
        boolean bRet = false;
        int processId = fragment.getProcessId();

        AddDeleteListAnimator listAnimator = mAddDeleteListAnimators.get(processId);
        if (listAnimator != null) {
            listAnimator.deleteFromAdapterCompleted();
            mAddDeleteListAnimators.remove(processId);
            bRet = true;
        }

        AddDeleteGridAnimator gridAnimator = mAddDeleteGridAnimators.get(processId);
        if (gridAnimator != null) {
            gridAnimator.deleteFromAdapterCompleted();
            mAddDeleteGridAnimators.remove(processId);
            bRet = true;
        }

        if (bRet) {
            mFragment = fragment;
        }

        if (mIsOnProgressDeleteVI) {
            bRet = true;
        }

        return bRet;
        */

    }

    private void _setDeleteListItem(int processId, Context context, AbsListView twListView, ArrayList<Integer> itemList) {
        //TODO HYL 删除动画
        /*
        AddDeleteListAnimator.OnAddDeleteListener listener = new AddDeleteListAnimator.OnAddDeleteListener() {
            @Override
            public void onAdd() {
            }

            @Override
            public void onAnimationEnd(boolean arg0) {
                onDeleteAnimationEnd();
            }

            @Override
            public void onAnimationStart(boolean arg0) {
                mIsOnProgressDeleteVI = true;
            }

            @Override
            public void onDelete() {
            }
        };

        AddDeleteListAnimator addDeleteListAnimator = new AddDeleteListAnimator(context, (ListView) twListView);
        addDeleteListAnimator.setOnAddDeleteListener(listener);
        addDeleteListAnimator.setDeletePending(itemList);
        mAddDeleteListAnimators.put(processId, addDeleteListAnimator);
        */
    }

    private void _setDeleteGridItem(int processId, Context context, AbsListView twListView, ArrayList<Integer> itemList) {
        //TODO HYL 删除动画
        /*
        AddDeleteGridAnimator.OnAddDeleteListener listener = new AddDeleteGridAnimator.OnAddDeleteListener() {
            @Override
            public void onAdd() {
            }

            @Override
            public void onAnimationEnd(boolean arg0) {
                onDeleteAnimationEnd();
            }

            @Override
            public void onAnimationStart(boolean arg0) {
                mIsOnProgressDeleteVI = true;
            }

            @Override
            public void onDelete() {
            }
        };

        AddDeleteGridAnimator addDeleteGridAnimator = new AddDeleteGridAnimator(context, (GridView) twListView);
        addDeleteGridAnimator.setOnAddDeleteListener(listener);
        addDeleteGridAnimator.setDeletePending(itemList);
        mAddDeleteGridAnimators.put(processId, addDeleteGridAnimator);
        */
    }

    private void onDeleteAnimationEnd() {
        if (mFragment != null) {
            mIsOnProgressDeleteVI = false;
            mFragment.finishActionMode();
            mFragment = null;
        }
    }

    public void startBottomSheet(View view, int initialHeight) {
        TranslateAnimation anim = new TranslateAnimation(0, 0, initialHeight, 0);
        anim.setDuration(300);
        anim.setInterpolator(PathInterpolatorCompat.create(0.33f, 0f, 0.2f, 1f));
        view.startAnimation(anim);
    }

    public void setEmptyViewAnimation(final Context context, final PathLineAnimationView pathLineAnimationView, final View mainText, final View subText, int rawId) {
        pathLineAnimationView.setSVG(rawId);
        pathLineAnimationView.setOnPathListener(new PathListener() {
            @Override
            public int getLineWidth(int position) {
                return DPUtils.dpToPx(2);
            }

            @Override
            public int getLineColor(int position) {
                return context.getResources().getColor(R.color.no_item_icon_color, context.getTheme());
            }

            @Override
            public Paint.Cap getLineCapStyle(int position) {
                return Paint.Cap.ROUND;
            }
        });
        pathLineAnimationView.setOnPathAnimatorListener(new EmptyIconPathAnimatorListener(rawId));

        ViewTreeObserver observer = pathLineAnimationView.getViewTreeObserver();
        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                pathLineAnimationView.getViewTreeObserver().removeOnPreDrawListener(this);
                startEmptyViewAnimation(pathLineAnimationView, mainText, subText);
                return true;
            }
        });
    }

    private void resetEmptyTextAnimation(View mainText, View subText) {
        mainText.setTranslationY(DPUtils.dpToPx(25));
        mainText.setAlpha(0);
        if (subText != null) {
            subText.setTranslationY(DPUtils.dpToPx(25));
            subText.setAlpha(0);
        }
    }

    private void startEmptyViewAnimation(PathLineAnimationView pathLineAnimationView, View mainText, View subText) {
        resetEmptyTextAnimation(mainText, subText);
        pathLineAnimationView.start();

        AnimatorSet set1 = createEmptyTextAnimatorSet(mainText);
        AnimatorSet set2 = createEmptyTextAnimatorSet(subText);

        AnimatorSet set = new AnimatorSet();
        set.playTogether(set1, set2);
        set.start();
    }

    private AnimatorSet createEmptyTextAnimatorSet(View textView) {
        final long transDuration = 500;
        final long alphaDuration = 333;
        AnimatorSet ret = new AnimatorSet();
        if (textView != null) {
            Animator transAnim = createTranslationAnimator(textView, transDuration, new SineInOut90());
            Animator alphaAnim = createAlphaAnimator(textView, alphaDuration, new SineInOut33());
            ret.playTogether(alphaAnim, transAnim);
        }
        return ret;
    }

    private Animator createTranslationAnimator(View view, long duration, Interpolator interpolator) {
        ObjectAnimator transAnim = null;
        if (view != null) {
            transAnim = ObjectAnimator.ofFloat(view, "translationY", 0f);
            transAnim.setDuration(duration);
            transAnim.setInterpolator(interpolator);
        }
        return transAnim;
    }

    private Animator createAlphaAnimator(View view, long duration, Interpolator interpolator) {
        ObjectAnimator alphaAnim = null;
        if (view != null) {
            alphaAnim = ObjectAnimator.ofFloat(view, "alpha", 1f);
            alphaAnim.setDuration(duration);
            alphaAnim.setInterpolator(interpolator);
        }
        return alphaAnim;
    }

    public void playGmsEmptyViewAnimation(View emptyView) {
        final long transDuration = 400;
        final long alphaDuration = 400;
        ArrayList<Animator> playAnimList = new ArrayList<>();

        View icon = emptyView.findViewById(R.id.icon);
        if (icon != null && icon instanceof LottieAnimationView) {
            ((LottieAnimationView) icon).playAnimation();
        }

        View message = emptyView.findViewById(R.id.message);
        if (message != null) {
            message.setTranslationY(DPUtils.dpToPx(20));
            message.setAlpha(0);
            playAnimList.add(createTranslationAnimator(message, transDuration, new SineInOut70()));
            playAnimList.add(createAlphaAnimator(message, alphaDuration, new SineInOut33()));
        }

        View storageUsageText = emptyView.findViewById(R.id.storage_usage_text);
        if (storageUsageText != null) {
            storageUsageText.setAlpha(0);
            playAnimList.add(createAlphaAnimator(storageUsageText, alphaDuration, new SineInOut33()));
        }

        View subText = emptyView.findViewById(R.id.storage_usage);
        if (subText != null) {
            subText.setAlpha(0);
            playAnimList.add(createAlphaAnimator(subText, alphaDuration, new SineInOut33()));
        }

        AnimatorSet set = new AnimatorSet();
        set.playTogether(playAnimList);
        set.setStartDelay(1000);
        set.start();
    }
}
